home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / machserver / 1.098 / ofs / ofsIndex.c < prev    next >
C/C++ Source or Header  |  1991-05-06  |  19KB  |  631 lines

  1. /* 
  2.  * ofsIndex.c --
  3.  *
  4.  *    Routines to allow moving through a files block pointers.  The method
  5.  *    of using these routines is the following:
  6.  *
  7.  *        1) Call OfsGetFirstIndex to get the first block.
  8.  *        2) Call OfsGetNextIndex to get subsequent blocks.
  9.  *        3) Call OfsEndIndex when finished.
  10.  *
  11.  *    There are flags to OfsGetFirstIndex that allow indirect blocks
  12.  *    to be deleted and allocated as appropriate.
  13.  *
  14.  *    The data structure operated on is the disk map kept in the disk
  15.  *    file descriptor (Fsdm_FileDescriptor).  This has 10 direct block pointers,
  16.  *    then a singly indirect block full of direct block pointers,
  17.  *    then a doubly indirect block full of singly indirect pointers.
  18.  *    The triple indirect block pointer is not implemented, limiting
  19.  *    the file size to 40K + 4Meg + 4Gigabytes.
  20.  *
  21.  * Copyright 1987 Regents of the University of California
  22.  * All rights reserved.
  23.  * Permission to use, copy, modify, and distribute this
  24.  * software and its documentation for any purpose and without
  25.  * fee is hereby granted, provided that the above copyright
  26.  * notice appear in all copies.  The University of California
  27.  * makes no representations about the suitability of this
  28.  * software for any purpose.  It is provided "as is" without
  29.  * express or implied warranty.
  30.  */
  31.  
  32. #ifndef lint
  33. static char rcsid[] = "$Header: /sprite/src/kernel/ofs/RCS/ofsIndex.c,v 9.5 90/12/11 01:02:14 mgbaker Exp $ SPRITE (Berkeley)";
  34. #endif not lint
  35.  
  36. #include <sprite.h>
  37. #include <fs.h>
  38. #include <fsutil.h>
  39. #include <fsNameOps.h>
  40. #include <fsio.h>
  41. #include <fslcl.h>
  42. #include <fscache.h>
  43. #include <fsStat.h>
  44. #include <spriteTime.h>
  45. #include <fsdm.h>
  46. #include <ofs.h>
  47.  
  48. static ReturnStatus MakePtrAccessible _ARGS_((Fsio_FileIOHandle *handlePtr,
  49.          OfsBlockIndexInfo *indexInfoPtr));
  50. static ReturnStatus FetchIndirectBlock _ARGS_((int indBlockNum,
  51.         Fsio_FileIOHandle *handlePtr, 
  52.         OfsBlockIndexInfo *indexInfoPtr, 
  53.         int *blockAddrPtr, int cacheBlockNum));
  54. static void FreeIndirectBlock _ARGS_((int indBlockNum, 
  55.         Fsio_FileIOHandle *handlePtr, OfsBlockIndexInfo *indexInfoPtr,
  56.         int *blockAddrPtr));
  57.  
  58.  
  59.  
  60. /*
  61.  *----------------------------------------------------------------------
  62.  *
  63.  * OfsGetFirstIndex --
  64.  *
  65.  *    Initialize the index structure.  This will set up the index info
  66.  *    structure so that it contains a pointer to the desired block pointer.
  67.  *
  68.  * Results:
  69.  *    A status indicating whether there was sufficient space to allocate
  70.  *    indirect blocks.
  71.  *
  72.  * Side effects:
  73.  *    The index structure is initialized.
  74.  *
  75.  *----------------------------------------------------------------------
  76.  */
  77.  
  78. ReturnStatus
  79. OfsGetFirstIndex(ofsPtr, handlePtr, blockNum, indexInfoPtr, flags)
  80.     Ofs_Domain              *ofsPtr;         /* Domain of file. */
  81.     Fsio_FileIOHandle          *handlePtr;    /* Handle for file that are 
  82.                           * indexing. */
  83.     int                  blockNum;      /* Where to start indexing. */
  84.     register OfsBlockIndexInfo *indexInfoPtr; /* Index structure to initialize.*/
  85.     int                  flags;         /* OFS_ALLOC_INDIRECT_BLOCKS,
  86.                         OFS_DELETE_INDIRECT_BLOCKS,
  87.                         OFS_DELETE_EVERYTHING,
  88.                         FSCACHE_DONT_BLOCK */
  89. {
  90.     register Fsdm_FileDescriptor     *descPtr;
  91.     int                      indirectBlock;
  92.     ReturnStatus        status = SUCCESS;
  93.  
  94.     indexInfoPtr->ofsPtr = ofsPtr,
  95.  
  96.     descPtr = handlePtr->descPtr;
  97.     indexInfoPtr->lastDiskBlock = FSDM_NIL_INDEX;
  98.     indexInfoPtr->indInfo[0].blockPtr = (Fscache_Block *) NIL;
  99.     indexInfoPtr->indInfo[0].deleteBlock = 0;
  100.     indexInfoPtr->indInfo[1].blockPtr = (Fscache_Block *) NIL;
  101.     indexInfoPtr->indInfo[1].deleteBlock = 0;
  102.     indexInfoPtr->flags = flags;
  103.     indexInfoPtr->blockNum = blockNum;
  104.  
  105.     if (blockNum < FSDM_NUM_DIRECT_BLOCKS) {
  106.     /*
  107.      * This is a direct block.
  108.      */
  109.     indexInfoPtr->indexType = OFS_DIRECT;
  110.     indexInfoPtr->directIndex = blockNum;
  111.     indexInfoPtr->blockAddrPtr = &(descPtr->direct[blockNum]);
  112.     return(SUCCESS);
  113.     }
  114.  
  115.     /*
  116.      * Is an indirect block.
  117.      */
  118.  
  119.     blockNum -= FSDM_NUM_DIRECT_BLOCKS;
  120.     indirectBlock = blockNum / FSDM_INDICES_PER_BLOCK;
  121.     if (indirectBlock == 0) {
  122.     /*
  123.      * This is a singly indirect block.
  124.      */
  125.     indexInfoPtr->indexType = OFS_INDIRECT;
  126.     indexInfoPtr->indInfo[0].index = blockNum;
  127.     if (flags & OFS_DELETE_EVERYTHING) {
  128.         indexInfoPtr->indInfo[0].deleteBlock = FSCACHE_DELETE_BLOCK;
  129.     }
  130.     } else if (indirectBlock < FSDM_INDICES_PER_BLOCK + 1) {
  131.     /*
  132.      * This a doubly indirect block.
  133.      */
  134.     indexInfoPtr->indexType = OFS_DBL_INDIRECT;
  135.     indexInfoPtr->indInfo[0].index = indirectBlock - 1;
  136.     indexInfoPtr->indInfo[1].index = 
  137.                 blockNum - indirectBlock * FSDM_INDICES_PER_BLOCK;
  138.     if (flags & OFS_DELETE_EVERYTHING) {
  139.         indexInfoPtr->indInfo[0].deleteBlock = FSCACHE_DELETE_BLOCK;
  140.         indexInfoPtr->indInfo[1].deleteBlock = FSCACHE_DELETE_BLOCK;
  141.     }
  142.     } else {
  143.     /*
  144.      * Past the largest file size that we support.
  145.      */
  146.     status = FS_INVALID_ARG;
  147.     }
  148.  
  149.     /*
  150.      * Finish off by making the block pointer accessible.  This may include
  151.      * reading indirect blocks into the cache.
  152.      */
  153.  
  154.     if (status == SUCCESS) {
  155.     status = MakePtrAccessible(handlePtr, indexInfoPtr);
  156.     }
  157.     return(status);
  158. }
  159.  
  160. /*
  161.  *----------------------------------------------------------------------
  162.  *
  163.  * OfsGetNextIndex --
  164.  *
  165.  *    Put the correct pointers in the index structure to access the
  166.  *    block after the current block.
  167.  *
  168.  * Results:
  169.  *    A status indicating whether there was sufficient space to allocate
  170.  *    indirect blocks if they were needed.
  171.  *
  172.  * Side effects:
  173.  *    The allocation structure is modified.  Indirect blocks may
  174.  *    be read into the cache.
  175.  *
  176.  *----------------------------------------------------------------------
  177.  */
  178.  
  179. ReturnStatus
  180. OfsGetNextIndex(handlePtr, indexInfoPtr, dirty)
  181.     Fsio_FileIOHandle          *handlePtr;    /* Handle for file that is being
  182.                         indexed. */
  183.     register OfsBlockIndexInfo *indexInfoPtr; /* Index structure to set up. */
  184.     Boolean              dirty;         /* True if allocated a new block
  185.                         so dirtied block pointer. */
  186. {
  187.     Boolean            accessible = FALSE;
  188.     register Fsdm_FileDescriptor    *descPtr = handlePtr->descPtr;
  189.  
  190.     indexInfoPtr->blockNum++;
  191.  
  192.     if (indexInfoPtr->blockAddrPtr != (int *) NIL &&
  193.     *indexInfoPtr->blockAddrPtr != FSDM_NIL_INDEX) {
  194.     indexInfoPtr->lastDiskBlock = 
  195.             *(indexInfoPtr->blockAddrPtr) / FS_FRAGMENTS_PER_BLOCK;
  196.     } else {
  197.     indexInfoPtr->lastDiskBlock = FSDM_NIL_INDEX;
  198.     }
  199.  
  200.     if (dirty) {
  201.     if (indexInfoPtr->indexType == OFS_INDIRECT) {
  202.         indexInfoPtr->indInfo[0].blockDirty = TRUE;
  203.     } else if (indexInfoPtr->indexType == OFS_DBL_INDIRECT) {
  204.         indexInfoPtr->indInfo[1].blockDirty = TRUE;
  205.     }
  206.     }
  207.     /*
  208.      * Determine whether we are now in direct, indirect or doubly indirect
  209.      * blocks.
  210.      */
  211.  
  212.     switch (indexInfoPtr->indexType) {
  213.     case OFS_DIRECT:
  214.         if (indexInfoPtr->blockNum < FSDM_NUM_DIRECT_BLOCKS) {
  215.         /*
  216.          * Still in the direct blocks.
  217.          */
  218.         indexInfoPtr->directIndex++;
  219.         indexInfoPtr->blockAddrPtr = 
  220.                 &(descPtr->direct[indexInfoPtr->directIndex]);
  221.         accessible = TRUE;
  222.         } else {
  223.         /*
  224.          * Moved into indirect blocks.
  225.          */
  226.         indexInfoPtr->indexType = OFS_INDIRECT;
  227.         indexInfoPtr->indInfo[0].index = 0;
  228.         if (indexInfoPtr->flags & OFS_DELETE_INDIRECT_BLOCKS) {
  229.             indexInfoPtr->indInfo[0].deleteBlock = FSCACHE_DELETE_BLOCK;
  230.         }
  231.         }
  232.         break;
  233.     case OFS_INDIRECT:
  234.         if (indexInfoPtr->blockNum < 
  235.             FSDM_NUM_DIRECT_BLOCKS + FSDM_INDICES_PER_BLOCK) {
  236.         /*
  237.          * Still in singly indirect blocks.
  238.          */
  239.         indexInfoPtr->indInfo[0].index++;
  240.         if (indexInfoPtr->indInfo[0].blockPtr != (Fscache_Block *) NIL) {
  241.             indexInfoPtr->blockAddrPtr++;
  242.         }
  243.         accessible = TRUE;
  244.         break;
  245.        } else {
  246.         /*
  247.          * Moved into doubly indirect blocks.
  248.          */
  249.         indexInfoPtr->indInfo[0].index = 0;
  250.         indexInfoPtr->indInfo[1].index = 0;
  251.         indexInfoPtr->indexType = OFS_DBL_INDIRECT;
  252.         /*
  253.          * Free up the indirect pointer block.
  254.          */
  255.         FreeIndirectBlock(0, handlePtr, indexInfoPtr, 
  256.             &descPtr->indirect[0]);
  257.         if (indexInfoPtr->flags & OFS_DELETE_INDIRECT_BLOCKS) {
  258.             indexInfoPtr->indInfo[0].deleteBlock = FSCACHE_DELETE_BLOCK;
  259.             indexInfoPtr->indInfo[1].deleteBlock = FSCACHE_DELETE_BLOCK;
  260.         }
  261.         }
  262.         break;
  263.     case OFS_DBL_INDIRECT:
  264.         indexInfoPtr->indInfo[1].index++;
  265.         if (indexInfoPtr->indInfo[1].index == FSDM_INDICES_PER_BLOCK) {
  266.         indexInfoPtr->indInfo[0].index++;
  267.         indexInfoPtr->indInfo[1].index = 0;
  268.         /*
  269.          * Free up the indirect pointer block.
  270.          */
  271.         FreeIndirectBlock(1, handlePtr, indexInfoPtr,
  272.             (int *) (indexInfoPtr->indInfo[0].blockPtr->blockAddr +
  273.             sizeof(int) * (indexInfoPtr->indInfo[0].index - 1)));
  274.         if (indexInfoPtr->indInfo[0].index == FSDM_INDICES_PER_BLOCK) {
  275.             /*
  276.              * We are at the end of the doubly indirect block and the
  277.              * caller wants us to go off of the end.  Free up the
  278.              * indirect block and return an error.
  279.              */
  280.             FreeIndirectBlock(0, handlePtr, indexInfoPtr,
  281.                  &(descPtr->indirect[FSDM_DBL_INDIRECT]));
  282.             return(FS_INVALID_ARG);
  283.         }
  284.         if (indexInfoPtr->flags & OFS_DELETE_INDIRECT_BLOCKS) {
  285.             indexInfoPtr->indInfo[1].deleteBlock = FSCACHE_DELETE_BLOCK;
  286.         }
  287.         } else {
  288.         if (indexInfoPtr->indInfo[1].blockPtr != 
  289.                         (Fscache_Block *) NIL) {
  290.             indexInfoPtr->blockAddrPtr++;
  291.         }
  292.         accessible = TRUE;
  293.         }
  294.         break;
  295.     }
  296.  
  297.     /*
  298.      * Make the block pointers accessible if necessary.
  299.      */
  300.  
  301.     if (!accessible) {
  302.     return(MakePtrAccessible(handlePtr, indexInfoPtr));
  303.     } else {
  304.     return(SUCCESS);
  305.     }
  306. }
  307.  
  308.  
  309. /*
  310.  *----------------------------------------------------------------------
  311.  *
  312.  * OfsEndIndex --
  313.  *
  314.  *    Free up cache blocks locked for indexing.  This also frees
  315.  *    a reference to the domain acquired with OfsGetFirstIndex.
  316.  *
  317.  * Results:
  318.  *    None.
  319.  *
  320.  * Side effects:
  321.  *    Cache blocks unlocked.
  322.  *
  323.  *----------------------------------------------------------------------
  324.  */
  325.  
  326. void
  327. OfsEndIndex(handlePtr, indexInfoPtr, dirty) 
  328.     Fsio_FileIOHandle          *handlePtr;    /* Handle for file that is being
  329.                         indexed. */
  330.     register OfsBlockIndexInfo *indexInfoPtr; /* Index structure to cleanup. */
  331.     Boolean              dirty;         /* True if allocated a new block
  332.                         so dirtied block pointer. */
  333. {
  334.     register Fsdm_FileDescriptor    *descPtr = handlePtr->descPtr;
  335.  
  336.     if (dirty) {
  337.     if (indexInfoPtr->indexType == FSDM_INDIRECT) {
  338.         indexInfoPtr->indInfo[0].blockDirty = TRUE;
  339.     } else if (indexInfoPtr->indexType == FSDM_DBL_INDIRECT) {
  340.         indexInfoPtr->indInfo[1].blockDirty = TRUE;
  341.     }
  342.     }
  343.     
  344.     /*
  345.      * Free up the second level indirect block and then the first level
  346.      * indirect block.
  347.      */
  348.  
  349.     if (indexInfoPtr->indInfo[1].blockPtr != (Fscache_Block *) NIL) {
  350.     FreeIndirectBlock(1, handlePtr, indexInfoPtr,
  351.             (int *) (indexInfoPtr->indInfo[0].blockPtr->blockAddr +
  352.                  sizeof(int) * indexInfoPtr->indInfo[0].index));
  353.     }
  354.     FreeIndirectBlock(0, handlePtr, indexInfoPtr,
  355.              &(descPtr->indirect[indexInfoPtr->indexType]));
  356. }
  357.  
  358. /*
  359.  *----------------------------------------------------------------------
  360.  *
  361.  * MakePtrAccessible --
  362.  *
  363.  *    Make the block pointer in the file descriptor accessible.  This
  364.  *    may entail reading in indirect blocks and locking them down in the
  365.  *    cache.
  366.  *
  367.  * Results:
  368.  *    None.
  369.  *
  370.  * Side effects:
  371.  *    Indirect blocks are locked down in the cache.
  372.  *
  373.  *----------------------------------------------------------------------
  374.  */
  375.  
  376. static ReturnStatus
  377. MakePtrAccessible(handlePtr, indexInfoPtr)
  378.     register    Fsio_FileIOHandle     *handlePtr;
  379.     register    OfsBlockIndexInfo     *indexInfoPtr;
  380. {
  381.     register    Fsdm_FileDescriptor     *descPtr;
  382.     register    int             *blockAddrPtr;
  383.     ReturnStatus            status;
  384.     int                    cacheBlockNum;
  385.  
  386.     descPtr = handlePtr->descPtr;
  387.  
  388.     if (indexInfoPtr->indexType == FSDM_INDIRECT) {
  389.     blockAddrPtr = &(descPtr->indirect[0]);
  390.     if (*blockAddrPtr == FSDM_NIL_INDEX && 
  391.         !(indexInfoPtr->flags & OFS_ALLOC_INDIRECT_BLOCKS)) {
  392.         indexInfoPtr->blockAddrPtr = (int *) NIL;
  393.         return(SUCCESS);
  394.     }
  395.     cacheBlockNum = -1;
  396.     } else {
  397.     blockAddrPtr = &(descPtr->indirect[1]);
  398.     cacheBlockNum = -2;
  399.     }
  400.  
  401.     /* 
  402.      * Lock the first level block into the cache.
  403.      */
  404.     status = FetchIndirectBlock(0, handlePtr, indexInfoPtr, blockAddrPtr,
  405.                 cacheBlockNum);
  406.     if (status != SUCCESS) {
  407.     return(status);
  408.     }
  409.     blockAddrPtr = (int *) (indexInfoPtr->indInfo[0].blockPtr->blockAddr + 
  410.                 sizeof(int) * indexInfoPtr->indInfo[0].index);
  411.  
  412.     if (indexInfoPtr->indexType == FSDM_INDIRECT) {
  413.     indexInfoPtr->blockAddrPtr = blockAddrPtr;
  414.     return(SUCCESS);
  415.     }
  416.  
  417.     /* 
  418.      * Lock the second level block into the cache.
  419.      */
  420.     if (*blockAddrPtr == FSDM_NIL_INDEX &&
  421.     !(indexInfoPtr->flags & OFS_ALLOC_INDIRECT_BLOCKS)) {
  422.     indexInfoPtr->blockAddrPtr = (int *) NIL;
  423.     return(SUCCESS);
  424.     }
  425.  
  426.     cacheBlockNum = 
  427.         -(3 + indexInfoPtr->indInfo[0].index);
  428.     status = FetchIndirectBlock(1, handlePtr, indexInfoPtr, blockAddrPtr,
  429.                 cacheBlockNum);
  430.     if (status == SUCCESS) {
  431.     indexInfoPtr->blockAddrPtr = 
  432.             (int *) (indexInfoPtr->indInfo[1].blockPtr->blockAddr + 
  433.              sizeof(int) * indexInfoPtr->indInfo[1].index);
  434.     } else {
  435.     FreeIndirectBlock(0, handlePtr, indexInfoPtr, &(descPtr->indirect[1]));
  436.     }
  437.     return(status);
  438. }
  439.  
  440. /*
  441.  *----------------------------------------------------------------------
  442.  *
  443.  * FetchIndirectBlock --
  444.  *
  445.  *    Read the indirect block into the cache.  Called by MakePtrAccessible
  446.  *    to fetch both indirect and doubly-indirect blocks.
  447.  *
  448.  * Results:
  449.  *    Error if could not read in or allocate indirect block.
  450.  *
  451.  * Side effects:
  452.  *    Indirect block is locked down in the cache.
  453.  *
  454.  *----------------------------------------------------------------------
  455.  */
  456.  
  457. static ReturnStatus
  458. FetchIndirectBlock(indBlockNum, handlePtr, indexInfoPtr, blockAddrPtr,
  459.            cacheBlockNum)
  460.     int                indBlockNum;    /* 0 if first level, 1 if 
  461.                          * second level indirect 
  462.                          * block. */
  463.     Fsio_FileIOHandle        *handlePtr;    /* File to fetch indirect
  464.                            * block for. */
  465.     register OfsBlockIndexInfo     *indexInfoPtr;  /* Indexing information for
  466.                          * this file. */
  467.     register int        *blockAddrPtr;    /* Disk block number. */
  468.     int                cacheBlockNum;    /* The block number by which
  469.                          * the cache knows this block.*/
  470. {
  471.     unsigned    char        *bitmapPtr;
  472.     int                blockNum;
  473.     Boolean            found;
  474.     ReturnStatus        status = SUCCESS;
  475.     register OfsIndirectInfo    *indInfoPtr;
  476.     register int        *intPtr;
  477.     Boolean            dontBlock;
  478. #ifdef SOSP91
  479.     Boolean        isForeign = FALSE;    /* Due to migration? */
  480. #endif SOSP91
  481.  
  482.     dontBlock = indexInfoPtr->flags & FSCACHE_DONT_BLOCK;
  483. #ifdef SOSP91
  484.     if (proc_RunningProcesses[0] != (Proc_ControlBlock *) NIL) {
  485.     if ((proc_RunningProcesses[0]->state == PROC_MIGRATED) ||
  486.         (proc_RunningProcesses[0]->genFlags &
  487.         (PROC_FOREIGN | PROC_MIGRATING))) {
  488.         isForeign = TRUE;
  489.     }
  490.     }
  491. #endif SOSP91
  492.  
  493.     indInfoPtr = &(indexInfoPtr->indInfo[indBlockNum]);
  494.     if (indInfoPtr->blockPtr == (Fscache_Block *) NIL) {
  495.     if (*blockAddrPtr == FSDM_NIL_INDEX) {
  496.         OfsBlockFind(handlePtr->hdr.fileID.minor, indexInfoPtr->ofsPtr, 
  497.             -1, TRUE, &blockNum, &bitmapPtr);
  498.         if (blockNum == -1) {
  499.         return(FS_NO_DISK_SPACE);
  500.         }
  501.         blockNum += indexInfoPtr->ofsPtr->headerPtr->dataOffset;
  502.         *blockAddrPtr = blockNum * FS_FRAGMENTS_PER_BLOCK;
  503.         handlePtr->descPtr->numKbytes += FS_FRAGMENTS_PER_BLOCK;
  504.         Fscache_FetchBlock(&handlePtr->cacheInfo, cacheBlockNum,
  505.         FSCACHE_IND_BLOCK|dontBlock, &(indInfoPtr->blockPtr), &found);
  506.         if (indInfoPtr->blockPtr == (Fscache_Block *)NIL) {
  507.         return(FS_WOULD_BLOCK);
  508.         }
  509.         if (found) {
  510.         /*
  511.          * The block should not be in the cache since we are just
  512.          * allocating it now.
  513.          */
  514.         panic("Physical block already in cache.\n");
  515.         }
  516.         for (intPtr = (int *)indInfoPtr->blockPtr->blockAddr;
  517.          (int)intPtr < (int)indInfoPtr->blockPtr->blockAddr + FS_BLOCK_SIZE;
  518.          intPtr++) {
  519.         *intPtr = FSDM_NIL_INDEX;
  520.         }
  521.         indexInfoPtr->indInfo[0].blockDirty = TRUE;
  522.         indexInfoPtr->indInfo[1].blockDirty = TRUE;
  523.         Fscache_IODone(indInfoPtr->blockPtr);
  524.     } else {
  525.         fs_Stats.blockCache.indBlockAccesses++;
  526. #ifdef SOSP91
  527.         if (isForeign) {
  528.         fs_SospMigStats.blockCache.indBlockAccesses++;
  529.         }
  530. #endif SOSP91
  531.         Fscache_FetchBlock(&handlePtr->cacheInfo, cacheBlockNum,
  532.         FSCACHE_IND_BLOCK|dontBlock, &(indInfoPtr->blockPtr), &found);
  533.         if (indInfoPtr->blockPtr == (Fscache_Block *)NIL) {
  534.         return(FS_WOULD_BLOCK);
  535.         }
  536.         if (!found) {
  537.         status = OfsDeviceBlockIO(indexInfoPtr->ofsPtr, FS_READ,
  538.                *blockAddrPtr, FS_FRAGMENTS_PER_BLOCK, 
  539.                indInfoPtr->blockPtr->blockAddr);
  540.         if (status == SUCCESS) {
  541.             fs_Stats.gen.physBytesRead += FS_BLOCK_SIZE;
  542.         }
  543.         Fscache_IODone(indInfoPtr->blockPtr);
  544.         } else {
  545.         fs_Stats.blockCache.indBlockHits++;
  546. #ifdef SOSP91
  547.         if (isForeign) {
  548.             fs_SospMigStats.blockCache.indBlockHits++;
  549.         }
  550. #endif SOSP91
  551.         }
  552.         indInfoPtr->blockDirty = FALSE;
  553.     }
  554.     }
  555.  
  556.     return(status);
  557. }
  558.  
  559. /*
  560.  *----------------------------------------------------------------------
  561.  *
  562.  * FreeIndirectBlock --
  563.  *
  564.  *    Remove the given block from the cache and, if appropriate, from disk.
  565.  *    This is called whenever OfsGetNextIndex or OfsEndIndex are 
  566.  *    finished with an indirect block that has previously been locked
  567.  *    into the cache by MakePtrAccessible.
  568.  *
  569.  * Results:
  570.  *    None.
  571.  *
  572.  * Side effects:
  573.  *    Block may be freed.
  574.  *
  575.  *----------------------------------------------------------------------
  576.  */
  577. static void
  578. FreeIndirectBlock(indBlockNum, handlePtr, indexInfoPtr, blockAddrPtr)
  579.     int                indBlockNum;    /* Which indirect block to 
  580.                          * free.*/
  581.     Fsio_FileIOHandle        *handlePtr;    /* File to delete indirect
  582.                          * block from. */
  583.     register OfsBlockIndexInfo     *indexInfoPtr;     /* Index structure to use. */
  584.     int                *blockAddrPtr;    /* Pointer to block to free. */
  585. {
  586.     int                modTime;
  587.     int                indBlock;
  588.     register    OfsIndirectInfo    *indInfoPtr;
  589. #ifdef SOSP91
  590.     Boolean        isForeign = FALSE;    /* Due to migration? */
  591. #endif SOSP91
  592.  
  593.     indInfoPtr = &indexInfoPtr->indInfo[indBlockNum];
  594.  
  595.     if (indInfoPtr->blockPtr != (Fscache_Block *) NIL) {
  596.     if (indInfoPtr->blockDirty) {
  597.         modTime = Fsutil_TimeInSeconds();
  598.         if (!indInfoPtr->deleteBlock) {
  599. #ifdef SOSP91
  600.         if (proc_RunningProcesses[0] != (Proc_ControlBlock *) NIL) {
  601.             if ((proc_RunningProcesses[0]->state == PROC_MIGRATED) ||
  602.                 (proc_RunningProcesses[0]->genFlags &
  603.                 (PROC_FOREIGN | PROC_MIGRATING))) {
  604.             isForeign = TRUE;
  605.             }
  606.         }
  607. #endif SOSP91
  608.         fs_Stats.blockCache.indBlockWrites++;
  609. #ifdef SOSP91
  610.         if (isForeign) {
  611.             fs_SospMigStats.blockCache.indBlockWrites++;
  612.         }
  613. #endif SOSP91
  614.         }
  615.     } else {
  616.         modTime = 0;
  617.     }
  618.     Fscache_UnlockBlock(indInfoPtr->blockPtr, 
  619.        (unsigned )modTime, -(*blockAddrPtr), FS_BLOCK_SIZE,
  620.        indInfoPtr->deleteBlock);
  621.     if (indInfoPtr->deleteBlock) {
  622.         indBlock = *blockAddrPtr / FS_FRAGMENTS_PER_BLOCK;
  623.         OfsBlockFree(indexInfoPtr->ofsPtr,
  624.             indBlock - indexInfoPtr->ofsPtr->headerPtr->dataOffset);
  625.         *blockAddrPtr = FSDM_NIL_INDEX;
  626.         handlePtr->descPtr->numKbytes -= FS_FRAGMENTS_PER_BLOCK;
  627.     }
  628.     indInfoPtr->blockPtr = (Fscache_Block *) NIL;
  629.     }
  630. }
  631.